package tws

import (
	"go-web-scaffold/api"
	"go-web-scaffold/config"

	"log"
	"net/http"
	"strings"

	"github.com/gin-gonic/gin"
)

var (
	globalConfig *config.GlobalConfig
)

type tws struct {
	mode          string
	ginServer     *GinServer
	routerManager *RouterManager
	useHandle     *UseFunc
	loadTemplate  *LoadTemplate
}

func New(path string) *tws {
	mode := ""
	if path == "" {
		mode += "default"
	} else {
		s := strings.Split(path, ".")
		if s[len(s)-1] != "json" {
			log.Fatal("path is invalid")
			return nil
		} else {
			mode = "non-default"
		}
	}
	config := _getGlobalConfig(path)
	if config == nil {
		log.Fatal("_getGlobalConfig is error")
		return nil
	}
	globalConfig = config

	tws := &tws{
		mode:      mode,
		ginServer: CreateServer(config),
		useHandle: NewUseFunc(),
	}
	tws.routerManager = NewRouterManager(tws.ginServer.engine)
	tws.loadTemplate = NewLoadTemplate("templates/", tws.ginServer.engine)
	return tws
}
func (_this *tws) Use(handle func(ctx *gin.Context)) {
	if handle == nil {
		log.Fatal("handle is nil")
		return
	}
	_this.useHandle.Add(handle)
}

func (_this *tws) GetRouterManager() *RouterManager {
	return _this.routerManager
}

func (_this *tws) NotFound404Error(message string) {
	if message == "" {
		log.Fatal("meessage is invalid")
		return
	}
	_this.ginServer.NotFound(func(ctx *gin.Context) {
		ctx.HTML(http.StatusOK, "not_found.tpl", gin.H{
			"data": message,
		})
	})
}
func (_this *tws) Run(callback func(engine *gin.Engine)) {
	if callback == nil {
		log.Fatal("callback is nil")
		return
	}
	serv := _this.ginServer
	_this.loadTemplate.AddResource("not_found.tpl")
	_this.loadTemplate.Load()
	serv.Start(func(engine *gin.Engine) {
		if _this.mode == "non-default" {
			_this._BootstrapNonDefaultMode()
		}
		if len(_this.useHandle.GetHandleFuncs()) > 0 {
			_this.useHandle.Do(engine)
		}
		callback(engine)
		_this._bindRouters(engine)
	})
}

func (_this *tws) _BootstrapNonDefaultMode() {
	_this.Use(func(ctx *gin.Context) {
		Authorize(ctx, func() {
			ctx.JSON(http.StatusUnauthorized, gin.H{"message": "访问未授权"})
		})
	})
	_this.Use(func(ctx *gin.Context) {
		RequestLimiter(ctx, func() {
			ctx.Writer.Write([]byte("请勿连续刷新页面"))
		})
	})

	_this.Use(func(ctx *gin.Context) {
		prefix := strings.Split(ctx.Request.RequestURI, "/")[1]
		if !AllowPrefix(prefix) {
			ctx.Writer.Write([]byte("非法访问"))
			ctx.Abort()
			return
		} else {
			ctx.Next()
		}
	})
}
func (_this *tws) _bindRouters(engine *gin.Engine) {
	_this.routerManager.BindRouters()
}

func _getGlobalConfig(path string) *config.GlobalConfig {
	if path == "" {
		log.Fatal("path is invalid")
		return nil
	}
	parser := api.NewConfigParser()
	parser.Add(path, &config.GlobalConfig{})
	globalConfig := parser.GetConfig(path)
	return globalConfig.(*config.GlobalConfig)
}
